package net.vanchu.mortgagecalculator.mortgage.data.calculator;

import net.vanchu.mortgagecalculator.common.config.LoanWay;
import net.vanchu.mortgagecalculator.mortgage.data.PrincipalAndInterest;
import net.vanchu.mortgagecalculator.mortgage.data.loan.AbsLoan;
import net.vanchu.mortgagecalculator.mortgage.data.loan.WithCommercial;
import net.vanchu.mortgagecalculator.mortgage.data.loan.WithProvidentFund;
import net.vanchu.mortgagecalculator.mortgage.data.monthRepayment.MixMonthRepay;
import net.vanchu.mortgagecalculator.mortgage.data.monthRepayment.MonthRepay;
import net.vanchu.mortgagecalculator.mortgage.data.monthRepayment.SingleMonthRepay;
import net.vanchu.mortgagecalculator.mortgage.data.repaymentSummary.PrincipalBalancedPart;
import net.vanchu.mortgagecalculator.mortgage.data.repaymentSummary.RepaySummary;
import net.vanchu.mortgagecalculator.mortgage.data.repaymentSummary.TotalBalancedPart;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Granton on 2016/12/21.
 */
class MixCalculator {

    static RepaySummary.Mix calRepaySummary(AbsLoan absLoan) {
        RepaySummary.Single repaySummaryCommercialPart = SingleCalculator.calRepaySummary(absLoan, true);
        RepaySummary.Single repaySummaryProvidentFundPart = SingleCalculator.calRepaySummary(absLoan, false);

        TotalBalancedPart.Mix tBalancedMix = getTBalancedMix(repaySummaryCommercialPart, repaySummaryProvidentFundPart);
        PrincipalBalancedPart.Mix pBalancedMix = getPBalancedMix(repaySummaryCommercialPart, repaySummaryProvidentFundPart);

        int numberOfMonths = absLoan.getYear() * 12;
        double principal = 0;
        if (absLoan instanceof WithCommercial) {
            principal += ((WithCommercial) absLoan).getCommercialPrincipal();
        }
        if (absLoan instanceof WithProvidentFund) {
            principal += ((WithProvidentFund) absLoan).getProvidentFundPrincipal();
        }
        return new RepaySummary.Mix(LoanWay.wayMix, numberOfMonths, principal, tBalancedMix, pBalancedMix);
    }

    private static PrincipalBalancedPart.Mix getPBalancedMix(RepaySummary.Single repaySummaryCom, RepaySummary.Single repaySummaryPro) {
        List<MixMonthRepay> monthRepays = combineMonthRepays(
                repaySummaryCom.getPrincipalBalancedPart().getSingleMonthRepays(),
                repaySummaryPro.getPrincipalBalancedPart().getSingleMonthRepays()
        );
        double decreaseNumber = repaySummaryCom.getPrincipalBalancedPart().getDecreaseNumber() +
                repaySummaryPro.getPrincipalBalancedPart().getDecreaseNumber();
        double firstRepayNumber = repaySummaryCom.getPrincipalBalancedPart().getFirstRepayNumber() +
                repaySummaryPro.getPrincipalBalancedPart().getFirstRepayNumber();
        return new PrincipalBalancedPart.Mix(
                decreaseNumber, firstRepayNumber, monthRepays,
                repaySummaryCom.getPrincipalBalancedPart().getPrincipalAndInterest(),
                repaySummaryPro.getPrincipalBalancedPart().getPrincipalAndInterest()
        );
    }

    private static TotalBalancedPart.Mix getTBalancedMix(RepaySummary.Single repaySummaryCom, RepaySummary.Single repaySummaryPro) {
        List<MixMonthRepay> monthRepays = combineMonthRepays(
                repaySummaryCom.getTotalBalancedPart().getSingleMonthRepays(),
                repaySummaryPro.getTotalBalancedPart().getSingleMonthRepays()
        );

        double numberRepayPerMonth =
                repaySummaryCom.getTotalBalancedPart().getNumberRepayPerMonth() +
                        repaySummaryPro.getTotalBalancedPart().getNumberRepayPerMonth();
        return new TotalBalancedPart.Mix(
                numberRepayPerMonth,
                monthRepays,
                repaySummaryCom.getTotalBalancedPart().getPrincipalAndInterest(),
                repaySummaryPro.getTotalBalancedPart().getPrincipalAndInterest());
    }

    private static List<MixMonthRepay> combineMonthRepays(
            List<SingleMonthRepay> comMonthRepays, List<SingleMonthRepay> proMonthRepays) {
        List<MixMonthRepay> result = new ArrayList<>();
        int size = comMonthRepays.size();
        MonthRepay comMonthRepay;
        MonthRepay proMonthPay;
        for (int i = 0; i < size; i++) {
            comMonthRepay = comMonthRepays.get(i);
            proMonthPay = proMonthRepays.get(i);
            MixMonthRepay mixMonthRepay = new MixMonthRepay(i + 1,
                    comMonthRepay.getRemainPrincipal() + proMonthPay.getRemainPrincipal(),
                    new PrincipalAndInterest(comMonthRepay.getTotalPrincipal(), comMonthRepay.getTotalInterest()),
                    new PrincipalAndInterest(proMonthPay.getTotalPrincipal(), proMonthPay.getTotalInterest()));
            result.add(mixMonthRepay);
        }
        return result;
    }
}